using Microsoft.Expression.Drawing.Core;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
namespace Microsoft.Expression.Media
{
	public sealed class SketchGeometryEffect : GeometryEffect
	{
		private const double expectedLengthMean = 8.0;
		private const double normalDisturbVariance = 0.5;
		private const double tangentDisturbVariance = 1.0;
		private const double bsplineWeight = 0.05;
		private readonly long randomSeed = DateTime.get_Now().get_Ticks();
		protected override GeometryEffect DeepCopy()
		{
			return new SketchGeometryEffect();
		}
		public override bool Equals(GeometryEffect geometryEffect)
		{
			return geometryEffect is SketchGeometryEffect;
		}
		protected override bool UpdateCachedGeometry(Geometry input)
		{
			bool flag = false;
			PathGeometry pathGeometry = input.AsPathGeometry();
			if (pathGeometry != null)
			{
				flag |= this.UpdateSketchGeometry(pathGeometry);
			}
			else
			{
				this.cachedGeometry = input;
			}
			return flag;
		}
		private bool UpdateSketchGeometry(PathGeometry inputPath)
		{
			bool flag = false;
			PathGeometry pathGeometry;
			flag = ((flag = (false | GeometryHelper.EnsureGeometryType<PathGeometry>(out pathGeometry, ref this.cachedGeometry, () => new PathGeometry()))) | pathGeometry.get_Figures().EnsureListCount(inputPath.get_Figures().get_Count(), () => new PathFigure()));
			RandomEngine random = new RandomEngine(this.randomSeed);
			for (int i = 0; i < inputPath.get_Figures().get_Count(); i++)
			{
				PathFigure pathFigure = inputPath.get_Figures().get_Item(i);
				bool isClosed = pathFigure.get_IsClosed();
				bool isFilled = pathFigure.get_IsFilled();
				if (pathFigure.get_Segments().get_Count() == 0)
				{
					flag = ((flag |= pathGeometry.get_Figures().get_Item(i).SetIfDifferent(PathFigure.StartPointProperty, pathFigure.get_StartPoint())) | pathGeometry.get_Figures().get_Item(i).get_Segments().EnsureListCount(0, null));
				}
				else
				{
					List<Point> list = new List<Point>(pathFigure.get_Segments().get_Count() * 3);
					using (IEnumerator<SimpleSegment> enumerator = this.GetEffectiveSegments(pathFigure).GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							SimpleSegment current = enumerator.get_Current();
							List<Point> list2 = new List<Point>();
							list2.Add(current.Points[0]);
							SimpleSegment arg_15B_0 = current;
							double tolerance = 0.0;
							IList<double> resultParameters = null;
							arg_15B_0.Flatten(list2, tolerance, resultParameters);
							PolylineData polyline = new PolylineData(list2);
							if (list2.get_Count() > 1 && polyline.TotalLength > 4.0)
							{
								double num = polyline.TotalLength / 8.0;
								int sampleCount = (int)Math.Max(2.0, Math.Ceiling(num));
								double interval = polyline.TotalLength / (double)sampleCount;
								double scale = interval / 8.0;
								List<Point> samplePoints = new List<Point>(sampleCount);
								List<Vector> sampleNormals = new List<Vector>(sampleCount);
								int sampleIndex = 0;
								PolylineHelper.PathMarch(polyline, 0.0, 0.0, delegate(MarchLocation location)
								{
									if (location.Reason == MarchStopReason.CompletePolyline)
									{
										return double.NaN;
									}
									if (location.Reason != MarchStopReason.CompleteStep)
									{
										return location.Remain;
									}
									if (sampleIndex++ == sampleCount)
									{
										return double.NaN;
									}
									samplePoints.Add(location.GetPoint(polyline.Points));
									sampleNormals.Add(location.GetNormal(polyline, 0.0));
									return interval;
								});
								SketchGeometryEffect.DisturbPoints(random, scale, samplePoints, sampleNormals);
								list.AddRange(samplePoints);
							}
							else
							{
								list.AddRange(list2);
								list.RemoveLast<Point>();
							}
						}
					}
					if (!isClosed)
					{
						list.Add(pathFigure.get_Segments().Last<PathSegment>().GetLastPoint());
					}
					flag |= PathFigureHelper.SyncPolylineFigure(pathGeometry.get_Figures().get_Item(i), list, isClosed, isFilled);
				}
			}
			if (flag)
			{
				this.cachedGeometry = PathGeometryHelper.FixPathGeometryBoundary(this.cachedGeometry);
			}
			return flag;
		}
		private static void DisturbPoints(RandomEngine random, double scale, IList<Point> points, IList<Vector> normals)
		{
			int count = points.get_Count();
			for (int i = 1; i < count; i++)
			{
				double num = random.NextGaussian(0.0, 1.0 * scale);
				double num2 = random.NextUniform(-0.5, 0.5) * scale;
				points.set_Item(i, new Point(points.get_Item(i).get_X() + normals.get_Item(i).X * num2 - normals.get_Item(i).Y * num, points.get_Item(i).get_Y() + normals.get_Item(i).X * num + normals.get_Item(i).Y * num2));
			}
		}
		private IEnumerable<SimpleSegment> GetEffectiveSegments(PathFigure pathFigure)
		{
			Point point = pathFigure.get_StartPoint();
			IEnumerator<PathSegmentData> enumerator = pathFigure.AllSegments().GetEnumerator();
			while (true)
			{
				IEnumerator<SimpleSegment> enumerator2;
				SimpleSegment current2;
				try
				{
					while (enumerator.MoveNext())
					{
						PathSegmentData current = enumerator.get_Current();
						enumerator2 = current.PathSegment.GetSimpleSegments(current.StartPoint).GetEnumerator();
						while (!enumerator2.MoveNext())
						{
							goto IL_7C;
							Block_4:
							try
							{
								point = current2.Points.Last<Point>();
								continue;
								IL_7C:;
							}
							finally
							{
								if (enumerator2 != null)
								{
									enumerator2.Dispose();
								}
							}
							goto JumpOutOfTryFinally2_3;
						}
						goto IL_116;
						JumpOutOfTryFinally2_3:;
					}
					break;
					IL_5D:
					goto Block_4;
				}
				finally
				{
					if (enumerator != null)
					{
						enumerator.Dispose();
					}
				}
				break;
				IL_116:
				current2 = enumerator2.get_Current();
				yield return current2;
				goto IL_5D;
			}
			if (pathFigure.get_IsClosed())
			{
				yield return SimpleSegment.Create(point, pathFigure.get_StartPoint());
			}
			yield break;
		}
	}
}
